1. Field of the Invention
The present invention relates to a program execution method for dynamically compiling a program that is created using a programming language, such as Java™. (“Java” is a trademark of Sun Microsystems, Inc.)
2. Description of the Related Art
With the growth in popularity of Java, the importance of providing an environment that is specially suited for the use of a dynamic compiler has increased. For an execution environment for Java in which a dynamic compiler is used, if all program optimization processing, for which an extended period of time is required, is performed at the time a program is initially compiled, depending on the compile time, a reduced processing speed will be attained by the program when it is executed. Therefore, for the initial running of a program, an interpreter is employed, or compiled code is used that was produced rapidly and for which no optimization processing was performed. At this time, data is acquired concerning the execution of the program, such as the execution count and information concerning the performance, including the number of iterations performed by each loop, and this data is subsequently used for optimization. By proceeding in this manner, the rapid execution of a program can be implemented.
A conventional, well known compiling method is one called adaptive compilation, as described in “Optimizing Dynamically-Typed Object-Oriented Programming Languages with Polymorphic Inline Caches,” Urs Hoelzle, Craig Chambers and David Ungar, in ECOOP '91 Conference Proceedings, pp. 21-38, Geneva, Switzerland, July 1991, published as Springer Verlag LNCS 512, 1991 [HCU91].
According to this method, compiling is performed substantially without optimization before a program is run the first time, and an invocation counter is employed to count the times the program is activated. Thereafter, when the activation count for a program exceeds a threshold value, an optimization count is incremented and recompiling is performed.
Since with this method a recompiled program is executed only at the time at which the pertinent method is called, the conventional method is not effective for a program that, even though it is activated only once, includes a loop or loops for which iterations are repeatedly performed, and that for its execution requires an extended period of time (includes a loop to be optimized, and a loop for which multiple iterations are performed).
A conventional method called deoptimization is also well known, as described in “Debugging Optimized Code With Dynamic Deoptimization,” Urs Hoelzle, Craig Chambers and David Ungar, in Proceedings of the SIGPLAN '92 Conference on Programming Language Design and Implementation, pp. 21-38, June 1992 [HCU92].
According to this method, unoptimized code that is created to debug code for an optimized method, and to perform the debugging of the execution program, is transferred to the obtained code. With this method, (1) before compiling is performed for optimization, interrupt points are designated at two positions: at the beginning of the method and at a branch command near the end of a loop; (2) optimization compiling is performed with an additional restriction that optimization that exceeds an interrupt point will not be performed; (3) when an interrupt is issued during program execution, the execution of the program is resumed following each interrupt point; and (4) a stack frame for the interrupt points is stored. Then, (5) a method is compiled without being optimized; and (6) the stack frame is reproduced in consonance with the non-optimized state, and the process enters an interrupt state. This method is similar to the present invention for transferring the process during the execution of a program. However, since a transfer target is un-optimized code, and since the execution condition, such as a register image, at the transfer point can be uniquely determined using source code, this conventional method can not be applied directly for a transfer to optimized code for which the process at the transfer destination becomes complex.
Further, a conventional well known method is called dynamic recompilation, as described in “Optimizing Dynamical-Dispatched Calls With Run-Time Type Feedback,” Urs Hoelzle and David Ungar, in Proceedings of the SIGPLAN '94 Conference on Programming Language Design and Implementation, pp. 326-336, published as SIGPLAN Notices 29(6), June 1994 [HU94].
This method is used to provide an explanation and an overview of a method whereby, during the execution of a non-optimized method, the pertinent method is replaced by one that was optimized when it was compiled. According to this method, (1) a method to be recompiled is detected, (2) a mark is set at a point at which execution is to be resumed, and (3) values that are pointed to by all the currently effective registers are calculated. When these processes have been successfully performed, (4) a non-optimized method in a stack is replaced by an optimized one. If such a replacement is disabled, generated code is called by a succeeding method and is employed. While detailed processing has not been explained for the above method, the following problems have arisen because, as it is described, the processing is the reverse of that performed in deoptimization [HCU92].
The problems with the above method are that a plurality of transfer points are not handled; that optimization passing beyond a transfer point is not performed; and that an increase in memory is not taken into account.
Two methods are available to switch the execution of a program when optimization compiling is performed: a method whereby an execution process is changed by calling the next method, and a method whereby a method that is being executed is replaced by optimized code. The second method, especially, is a function required to increase the processing speed for a method that includes a loop for which multiple iterations are performed, even though it is activated only once, and that for its execution requires an extended period of time. However, when the conventional method, whereby the methods are switched during execution, is employed, the following two problems are encountered.
First, optimization does not pass beyond a position (hereinafter referred to a transfer point) in a method that is to be switched. Therefore, if a transfer point is present, the quality of code obtained is lower than the code that is generated when there is no transfer point. The execution speed for a program when a succeeding method is called is lower than the execution speed obtained when optimization compiling is performed while no transfer point is present.
Especially when a transfer point has been inserted into a loop, optimization of the loop, which can greatly affect the execution performance, can not be performed, and as a result, considerable degradation of the performance occurs.
Second, no consideration is given to a case in a multithreaded environment in which processes are replaced at a plurality of different transfer points, and compiling is performed each time a transfer occurs. These multiple compiling sessions contribute to the deterioration of the execution speed; generated codes overlap and the consumption of memory is increased.